import { APP, ClientApp, ClientAppDic, IPowerED,IGlobalState } from "./types"
import _cloneDeep from "lodash/cloneDeep";
import { changeStringToDom } from './html'
import { ConsoleLogger } from './debug-log'
import { App ,activeApp} from "./microApp"
import { getHtmlContent } from "./httpServer"
const console = new ConsoleLogger('微应用-主应用')

export const start = (debug=true) => { 
  window.__POWERED_BY_MICO__ = { activeAppDic: {}, partitionAppDic: {},clientAppDicProxy:{},debugger: debug, globalState:{}}
  console.log('开启微应用-主应用初始化');
}

/**
 * 微应用注册
 * @param baseUrl url路径
 * @param name  应用名称，name需要唯一
 */
export const loadMicro = async (param: Pick<APP, 'domId' | 'name' | 'baseUrl'>) => {
  const dic = window.__POWERED_BY_MICO__;
  try {

    if(dic.partitionAppDic[param.name]){
      await activeApp(dic.partitionAppDic[param.name]);
      return dic.activeAppDic[param.name];
    }
    //判断是否已经是激活状态
    if(dic.activeAppDic[param.name]){
      const app_tmp=dic.activeAppDic[param.name];
      document.getElementById(app_tmp.domId.replace('#','')).innerHTML=""
      document.getElementById(app_tmp.domId.replace('#','')).appendChild(app_tmp.htmlElement);
      return app_tmp;
    }
    const html = await getHtmlContent(param.baseUrl);
    const htmlinfo = await changeStringToDom(param.baseUrl,html, param.name);
    //创建微应用
    const app: APP = new App({
      name: param.name, appJs: htmlinfo.jsData, appCss: htmlinfo.cssData, domId: param.domId,
      htmlContent: html, baseUrl: param.baseUrl, htmlElement: htmlinfo.contain
    })
    dic.activeAppDic[param.name] = app;
    console.log('加载微引用成功,后续将执行子应用microClientBind', { app: { ...dic.activeAppDic[param.name] } });
    app.bootstrap();
    app.mount(); 
    return app
  } catch (e) {
    console.warn('加载子应用失败', { e })
    if(dic.activeAppDic[param.name]){
      delete dic.activeAppDic[param.name];
    }
    throw new Error("加载子应用失败")
  }
}


class GlobalState implements IGlobalState{
  global={}
  globalStateChangeFn=[]
  constructor(state:Record<string,any>){ 
      const proxy=new Proxy({},{ 
         set:(target, propKey:string, value, receiver)=>{ 
          this.globalStateChangeFn.forEach(fn=>fn(value,target[propKey])) 
           target[propKey] = value; 
           return true
         }
      })
    this.global=proxy;
    this.global['state']=_cloneDeep(state);
  }
  onGlobalStateChange=(fn)=>{
    this.globalStateChangeFn.push(fn)
  }
  setGlobalState= (state: Record<string, any>) => {
    this.global['state']=state;
  } 
}
/**
 * 初始化全局字段共享数据
 */
export const initGlobalState = (state:Record<string,any>) => {
  const st= window.__POWERED_BY_MICO__.globalState= new GlobalState(state);  
   return st;
}

declare global {
  interface Window {
    __POWERED_BY_MICO__: IPowerED;
    exec:any
    proxy:any
  }
}
